﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using OxyPlot;
using OxyPlot.Xps;
using System.Windows;

namespace DesicionTreeViewer
{
    enum TLeafType {
        LT_FirstTypeNode,
        LT_SecondTypeNode,

        LT_NotDefined
    }
    //узел дерева классификации
    class ClassificationTreeItem : TreeViewItem
    {
        private HashSet<int> secondTypeDataFilter;
        private HashSet<int> firstTypeDataFilter;
        private HashSet<int> observableDataFilter;
        private ClassificationLine classificationLine;
        private int firstProperty;
        private int secondProperty;
        private bool hasToFilterUnderLinePoint;
        private bool hasClassificationLine;
        private TLeafType leafType;

        public TLeafType LeafType
        {
            get { return leafType; }
            set { leafType = value; }
        }

        public String LineDescription
        {
            get
            {
                return string.Format("y = {0} * x + {1}", classificationLine.Slope, classificationLine.Intercept);
            }
        }

        public bool HasClassificationLine
        {
            get { return hasClassificationLine;  }
        }

        public bool FilterUnderLinePoint
        {
            get { return hasToFilterUnderLinePoint; }
        }

        public int FirstProperty
        {
            get { return firstProperty; }
        }

        public int SecondProperty
        {
            get { return secondProperty; }
        }

        public HashSet<int> SecondTypeDataFilter
        {
            get { return secondTypeDataFilter; }
        }

        public HashSet<int> FirstTypeDataFilter
        {
            get { return firstTypeDataFilter; }
        }

        public HashSet<int> ObservationFilter
        {
            get { return observableDataFilter; }
        }

        public ClassificationLine Line
        {
            get { return classificationLine.Clone(); }
            set { classificationLine = value.Clone(); }
        }

        public ClassificationTreeItem( ClassificationTreeItem parent, CLoadedData secondTypeData, CLoadedData firstTypeData, CLoadedData observations,
            int _firstProperty, int _secondProperty, bool _hastoFilterUnderLinePoints, ClassificationLine line, bool _hasClassificationLine )
        {
            HashSet<int> parentSecondTypeDataFilter = null;
            HashSet<int> parentFirstTypeDataFilter = null;
            HashSet<int> parentObservationFilter = null;

            if (parent != null)
            {
                parentSecondTypeDataFilter = parent.SecondTypeDataFilter;
                parentFirstTypeDataFilter = parent.FirstTypeDataFilter;
                parentObservationFilter = parent.ObservationFilter;
            }

            firstProperty = _firstProperty;
            secondProperty = _secondProperty;
            classificationLine = line.Clone();
            hasToFilterUnderLinePoint = _hastoFilterUnderLinePoints;
            hasClassificationLine = _hasClassificationLine;
            leafType = TLeafType.LT_NotDefined;
            //инициализируем фильтры
            adjustFilter(ref secondTypeDataFilter, parentSecondTypeDataFilter, secondTypeData, hasToFilterUnderLinePoint);
            adjustFilter(ref firstTypeDataFilter, parentFirstTypeDataFilter, firstTypeData, hasToFilterUnderLinePoint);
            adjustFilter(ref observableDataFilter, parentObservationFilter, observations, hasToFilterUnderLinePoint);
        }

        private void adjustFilter( ref HashSet<int> adjustableFilter, HashSet<int> oldFilter,
            CLoadedData dataStorage, bool hastoFilterUnderLinePoints)
        {
            if (oldFilter == null)
            {
                adjustableFilter = new HashSet<int>();
            }
            else
            {
                adjustableFilter = new HashSet<int>( oldFilter );
            }

            if (!hasClassificationLine)
            {
                return;
            }

            if (dataStorage.TrainingDataSize == 0)
            {
                return;
            }

            //получим нужные точки
            List<double> allXPoints = dataStorage.Data[firstProperty].Value;
            List<double> allYPoints = dataStorage.Data[secondProperty].Value;

            //отсеим их 
            int curIndex = 0;
            List<double>.Enumerator xEnumerator = allXPoints.GetEnumerator();
            List<double>.Enumerator yEnumerator = allYPoints.GetEnumerator();

            while (xEnumerator.MoveNext() && yEnumerator.MoveNext())
            {
                DataPoint candidatePoint =
                    new DataPoint(xEnumerator.Current, yEnumerator.Current);

                if (hastoFilterUnderLinePoints)
                {
                    if (classificationLine.IsUnderLine(candidatePoint))
                    {
                        adjustableFilter.Add(curIndex);
                    }
                }

                if (!hastoFilterUnderLinePoints)
                {
                    if (!classificationLine.IsUnderLine(candidatePoint))
                    {
                        adjustableFilter.Add(curIndex);
                    }
                }

                curIndex++;
            }
        }
       
    }
}
